package com.duoqin.syncassistant.viewmodel;

import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.Toast;

import com.duoqin.common.data.QRCodeResponse;
import com.duoqin.common.data.remote.ApiClient;
import com.duoqin.syncassistant.R;
import com.duoqin.syncassistant.data.remote.AppServerApiInterface;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class AppViewModel extends BaseViewModel {
    private static final String TAG = "duoqin_AppViewModel";

    public static final String APP_QRCODE_FILE = "qrCode.png";
    public static final String QRCODE_FILE = "qr.png";
    public static final Object appLockObj = new Object();
    public static final Object qrCodeLockObj = new Object();

    private AppServerApiInterface mApiInterface;
    private MutableLiveData<QRCodeResponse> mAppQRCodeResponse;
    private MutableLiveData<QRCodeResponse> mQRCodeResponse;

    public AppViewModel(@NonNull Application application) {
        super(application);
        mApiInterface = ApiClient.getAppClient().create(AppServerApiInterface.class);
    }

    public LiveData<QRCodeResponse> appQRCodeResponse() {
        if (mAppQRCodeResponse == null) {
            mAppQRCodeResponse = new MutableLiveData<>();
        }
        return mAppQRCodeResponse;
    }

    public void getAppQRCode() {
        Log.d(TAG, "getAppQRCode");

        final Call<ResponseBody> call = mApiInterface.getAppQRCode("Android",
                "com.duoqin.duoqinassistant");
        if (call != null) {
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    Log.d(TAG, "onResponse = " + response);
                    if (response != null && mAppQRCodeResponse != null) {
                        if (200 == response.code()) {
                            try {
                                Log.d(TAG, "body = " + response.body());
                                synchronized (AppViewModel.appLockObj) {
                                    File file = new File(getApplication().getCacheDir(), APP_QRCODE_FILE);
                                    if (file.exists()) {
                                        file.delete();
                                    }
                                    InputStream is = response.body().byteStream();
                                    FileOutputStream fos = new FileOutputStream(file);
                                    BufferedInputStream bis = new BufferedInputStream(is);
                                    byte[] buffer = new byte[1024];
                                    int len;
                                    while ((len = bis.read(buffer)) != -1) {
                                        fos.write(buffer, 0, len);
                                    }
                                    fos.flush();
                                    fos.close();
                                    bis.close();
                                    is.close();

                                    Log.d(TAG, "qrCode received = " + file.getAbsolutePath());

                                    QRCodeResponse qrCodeResponse = new QRCodeResponse();
                                    qrCodeResponse.setCode(SERVER_RESULT_SUCCESS);
                                    qrCodeResponse.setQrCode(file.getAbsolutePath());
                                    mAppQRCodeResponse.setValue(qrCodeResponse);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        } else {
                            try {
                                String errorString = response.errorBody().string();
                                Log.w(TAG, "error " + errorString);
                                JSONObject jsonObject = new JSONObject(errorString);
                                QRCodeResponse errorResponse = new QRCodeResponse();
                                errorResponse.setCode(jsonObject.getInt("code"));
                                errorResponse.setMsg(jsonObject.getString("msg"));
                                mAppQRCodeResponse.setValue(errorResponse);
                            } catch (IOException | JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Log.e(TAG, t.toString());
                    if (mAppQRCodeResponse != null) {
                        mAppQRCodeResponse.setValue(null);
                    }
                }
            });
        }
    }

    public LiveData<QRCodeResponse> qrCodeResponse() {
        if (mQRCodeResponse == null) {
            mQRCodeResponse = new MutableLiveData<>();
        }
        return mQRCodeResponse;
    }

    public void getQRCode(String payload) {
        Log.d(TAG, "getQRCode payload = " + URLEncoder.encode(payload));

        final Call<ResponseBody> call = mApiInterface.getQRCode(URLEncoder.encode(payload));
        if (call != null) {
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    Log.d(TAG, "onResponse = " + response);
                    if (mQRCodeResponse != null) {
                        if (200 == response.code()) {
                            try {
                                Log.d(TAG, "body = " + response.body());
                                synchronized (AppViewModel.qrCodeLockObj) {
                                    File file = new File(getApplication().getCacheDir(), QRCODE_FILE);
                                    if (file.exists()) {
                                        file.delete();
                                    }
                                    InputStream is = response.body().byteStream();
                                    FileOutputStream fos = new FileOutputStream(file);
                                    BufferedInputStream bis = new BufferedInputStream(is);
                                    byte[] buffer = new byte[1024];
                                    int len;
                                    while ((len = bis.read(buffer)) != -1) {
                                        fos.write(buffer, 0, len);
                                    }
                                    fos.flush();
                                    fos.close();
                                    bis.close();
                                    is.close();

                                    Log.d(TAG, "qrCode received = " + file.getAbsolutePath());

                                    QRCodeResponse qrCodeResponse = new QRCodeResponse();
                                    qrCodeResponse.setCode(SERVER_RESULT_SUCCESS);
                                    qrCodeResponse.setQrCode(file.getAbsolutePath());
                                    mQRCodeResponse.setValue(qrCodeResponse);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        } else {
                            try {
                                String errorString = response.errorBody().string();
                                Log.w(TAG, "error " + errorString);
                                JSONObject jsonObject = new JSONObject(errorString);
                                QRCodeResponse errorResponse = new QRCodeResponse();
                                errorResponse.setCode(jsonObject.getInt("code"));
                                errorResponse.setMsg(jsonObject.getString("msg"));
                                mQRCodeResponse.setValue(errorResponse);
                            } catch (IOException | JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Log.e(TAG, t.toString());
                    Toast.makeText(getApplication(), R.string.network_error_default,
                            Toast.LENGTH_SHORT).show();
                    if (mQRCodeResponse != null) {
                        mQRCodeResponse.setValue(null);
                    }
                }
            });
        }
    }

}
